﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Xml.Serialization
Imports System.Web

Namespace roncliProductions.LibWowArmory

    Public Class CharacterAchievementsCategory
        Inherits WowArmoryData

#Region "Declarations"

        Private cacAchievements As New CharacterAchievementsCategorySchema.achievements
        Private strRealm As String
        Private strName As String
        Private intCategoryID As Integer
        Private cCategory As New Category

#End Region

        ''' <summary>
        ''' The realm the character is on
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Realm() As String
            Get
                Return strRealm
            End Get
            Set(ByVal value As String)
                strRealm = value
            End Set
        End Property

        ''' <summary>
        ''' The name of the character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Name() As String
            Get
                Return strName
            End Get
            Set(ByVal value As String)
                strName = value
            End Set
        End Property

        ''' <summary>
        ''' The identification number of the achievement category
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property CategoryID() As Integer
            Get
                Return intCategoryID
            End Get
            Set(ByVal value As Integer)
                intCategoryID = value
            End Set
        End Property

        ''' <summary>
        ''' The URL that will be used to retrieve the character's achievements from the Armory
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL() As String
            Get
                Return String.Format("http://www.wowarmory.com/character-achievements.xml?r={0}&n={1}&c={2}", strRealm, strName, intCategoryID)
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request does not require login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin() As Boolean
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' The achievements for this category
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Achievements() As Category
            Get
                Return cCategory
            End Get
        End Property

        ''' <summary>
        ''' A constructor to load a character's achievements by realm and character name
        ''' </summary>
        ''' <param name="strRealm"></param>
        ''' <param name="strName"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal strRealm As String, ByVal strName As String, ByVal intCategoryID As Integer)
            Me.strRealm = strRealm
            Me.strName = strName
            Me.intCategoryID = intCategoryID
            Load()
        End Sub

        ''' <summary>
        ''' Loads the character's achievements for this category from the armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Load()
            Dim strKey As String = String.Format("LibWowArmory.CharacterAchievementsCategory.{0}.{1}.{2}", strRealm, strName, intCategoryID)
            If Cache.Cache(strKey) Is Nothing Then
                MyBase.Retrieve()

                Dim xsSerializer As New XmlSerializer(cacAchievements.GetType())

                Dim srXML As New StringReader(MyBase.strData)

                cacAchievements = CType(xsSerializer.Deserialize(srXML), CharacterAchievementsCategorySchema.achievements)

                Cache.Cache.Insert(strKey, cacAchievements, Nothing, Date.UtcNow.AddDays(1), Nothing, Caching.CacheItemPriority.Normal, Nothing)
            Else
                cacAchievements = CType(Cache.Cache(strKey), CharacterAchievementsCategorySchema.achievements)
            End If

            If cacAchievements Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If
            If cacAchievements.category Is Nothing Then
                Throw New ArgumentException("The character you are trying to retrieve achievements for does not exist.")
            End If

            ProcessCategory(cCategory, cacAchievements.category.First())
        End Sub

        Private Sub ProcessCategory(ByRef cCategory As Category, ByRef cacCategory As CharacterAchievementsCategorySchema.category)
            For Each cacAchievement As CharacterAchievementsCategorySchema.achievement In cacCategory.achievement
                Dim aAchievement As New Achievement(cacAchievement.categoryId, cacAchievement.dateCompleted, cacAchievement.desc, cacAchievement.icon, cacAchievement.id, cacAchievement.points, cacAchievement.reward, cacAchievement.title)
                ProcessAchievement(aAchievement, cacAchievement)
                For Each cacCriteria As CharacterAchievementsCategorySchema.criteria In cacAchievement.criteria
                    aAchievement.AchievementCriteria.Add(New Achievement.Criteria(cacCriteria.date, cacCriteria.id, cacCriteria.maxQuantity, cacCriteria.maxQuantityGold * 10000, cacCriteria.name, cacCriteria.quantity, cacCriteria.quantityGold * 10000 + cacCriteria.quantitySilver * 100 + cacCriteria.quantityCopper))
                Next
                cCategory.Achievements.Add(aAchievement)
            Next
            For Each cacSubcategory As CharacterAchievementsCategorySchema.category In cacCategory.category
                Dim cSubcategory As New Category
                ProcessCategory(cSubcategory, cacSubcategory)
                cCategory.Subcategories.Add(cSubcategory)
            Next
        End Sub

        Private Sub ProcessAchievement(ByRef aAchievement As Achievement, ByRef cacAchievement As CharacterAchievementsCategorySchema.achievement)
            For Each cacSubachievement As CharacterAchievementsCategorySchema.achievement In cacAchievement.achievement
                Dim aSubachievement As New Achievement(cacSubachievement.categoryId, cacSubachievement.dateCompleted, cacSubachievement.desc, cacSubachievement.icon, cacSubachievement.id, cacSubachievement.points, cacSubachievement.reward, cacSubachievement.title)
                ProcessAchievement(aSubachievement, cacSubachievement)
                For Each cacCriteria As CharacterAchievementsCategorySchema.criteria In cacSubachievement.criteria
                    aSubachievement.AchievementCriteria.Add(New Achievement.Criteria(cacCriteria.date, cacCriteria.id, cacCriteria.maxQuantity, cacCriteria.maxQuantityGold * 10000, cacCriteria.name, cacCriteria.quantity, cacCriteria.quantityGold * 10000 + cacCriteria.quantitySilver * 100 + cacCriteria.quantityCopper))
                Next
                aAchievement.PreviousAchievements.Add(aSubachievement)
            Next
        End Sub

        ''' <summary>
        ''' A class that encapsulates achievement category information
        ''' </summary>
        ''' <remarks></remarks>
        Public Class Category

            Private aAchievements As New List(Of Achievement)
            Private cSubcategories As New List(Of Category)

            ''' <summary>
            ''' The achievements in this category
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Achievements() As List(Of Achievement)
                Get
                    Return aAchievements
                End Get
                Set(ByVal value As List(Of Achievement))
                    aAchievements = value
                End Set
            End Property

            ''' <summary>
            ''' The subcategories listed in this category
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Subcategories() As List(Of Category)
                Get
                    Return cSubcategories
                End Get
                Set(ByVal value As List(Of Category))
                    cSubcategories = value
                End Set
            End Property

        End Class

    End Class

End Namespace